﻿using NUnit.Framework;
using Sasa.QualityTools.CodeAnalysis.Core.Models;
using Sasa.QualityTools.CodeAnalysis.MSBuild.Tests.Unit.Instruments;
using System;
using System.IO;

namespace Sasa.QualityTools.CodeAnalysis.MSBuild.Tests.Unit
{
    [TestFixture]
    public class PerformCodeMetricsCalculationTest
    {
        private static readonly string SolutionDir = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "..", ".."));

        private static readonly string ProjectDir = Path.Combine(SolutionDir, "TestTarget");

        private static readonly string TargetPath = Path.Combine(Environment.CurrentDirectory.Replace(Path.Combine(SolutionDir, "MSBuild.Tests.Unit"), ProjectDir), "TestTarget.dll");

        private static readonly string ReportPath = Path.Combine(Path.GetDirectoryName(TargetPath), Core.Constants.CodeMetricsReportFileName);

        private static readonly string TaskName = "PerformCodeMetricsCalculation";


        [Test]
        public void ExecuteShouldFailWhenTargetPathIsNotSpecified()
        {
            var taskParameter = String.Format("SolutionDir='{0}' ProjectDir='{1}' References='dummy'", SolutionDir, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }

        [Test]
        public void ExecuteShouldFailWhenProjectDirIsNotSpecified()
        {
            var taskParameter = String.Format("TargetPath='{0}' SolutionDir='{1}' References='dummy'", TargetPath, SolutionDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }

        [Test]
        public void ExecuteShouldFailWhenSolutionDirIsNotFound()
        {
            var taskParameter = String.Format("TargetPath='{0}' ProjectDir='C:\\' References='dummy'", TargetPath, SolutionDir, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }

        [Test]
        public void ExecuteShouldFailWhenReferencesIsNotSpecified()
        {
            var taskParameter = String.Format("TargetPath='{0}' SolutionDir='{1}' ProjectDir='{2}'", TargetPath, SolutionDir, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }

        [Test]
        public void ExecuteShouldFailWhenCodeInspectionFailed()
        {
            var projectDir = Path.Combine(SolutionDir, "TestTarget.ReferenceError");
            var targetPath = Path.Combine(Environment.CurrentDirectory.Replace(Path.Combine(SolutionDir, "MSBuild.Tests.Unit"), ProjectDir), "TestTarget.ReferenceError.dll");
            var reference = GetType().Assembly.Location;
            var taskParameter = String.Format("TargetPath='{0}' SolutionDir='{1}' ProjectDir='{2}' References='{3}'", targetPath, SolutionDir, projectDir, reference);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }


        [Test]
        public void ExecuteShouldFailWhenMetricsPathIsNotValid()
        {
            var taskParameter = String.Format("MetricsPath='notexist.exe' TargetPath='{0}' SolutionDir='{1}' ProjectDir='{2}' References='dummy'", TargetPath, SolutionDir, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);
            Assert.IsFalse(result.Success);
        }

        [Test]
        public void ExecuteShouldPerformCodeInspection()
        {
            if (File.Exists(ReportPath))
            {
                File.Delete(ReportPath);
            }

            var taskParameter = String.Format("TargetPath='{0}' SolutionDir='{1}' ProjectDir='{2}' References='dummy'", TargetPath, SolutionDir, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);

            Assert.IsTrue(result.Success);

            var report = new MetricsReport();
            report.Load(ReportPath);
            Assert.AreEqual(18, report.MetricValues.Count);
        }

        [Test]
        public void ExecuteShouldPerformCodeInspectionWhenSolutionDirProbeSucceeded()
        {
            if (File.Exists(ReportPath))
            {
                File.Delete(ReportPath);
            }

            var taskParameter = String.Format("TargetPath='{0}' ProjectDir='{1}' References='dummy'", TargetPath, ProjectDir);
            var runner = new MSBuildTaskRunner();
            var result = runner.Run(TaskName, taskParameter);

            Assert.IsTrue(result.Success);

            var report = new MetricsReport();
            report.Load(ReportPath);
            Assert.AreEqual(18, report.MetricValues.Count);
        }
    }
}
